/* controller.c
 * This file is part of the Tisa Project.
 *  
 * Authors: Cleiber Marques da Silva <cleiber.dev@gmail.com>
 *          Odilson Tadeu Valle <odilson@sj.cefetsc.edu.br>
 *
 * Tisa Project is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; version 2 of
 * the License.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <pthread.h>

#include "tisa.h"
#include "tqueue.h"
#include "socket.h"
#include "log.h"

static char *get_variable_string(int variable)
{
	switch (variable) {
	case Ta:
		return "sta0";
	case T:
		return "st-0";
	case Ti:
		return "sti0";
	case No:
		return "sno0";
	case H:
		return "sh-0";
	case Ni:
		return "ani";
	case Q:
		return "aq-";
	case TREF:
		return "TRef";
	case HREF:
		return "HRef";
	default:
		return "";
	}
}

static inline float boiler_get_value(struct boiler *heater, int variable)
{
	int bytes;
	char msg[BUFF_SIZE];

	send_msg(heater->sock_fd, heater->server, get_variable_string(variable));
	bytes = recv_msg(heater->sock_fd, msg);
	msg[bytes] = 0; /* receive without EOF */
	return atof(msg + 3);
}

static inline void boiler_put_value(struct boiler *heater, int variable)
{
	int i;
	char msg[BUFF_SIZE];

	i = sprintf(msg, "%s", get_variable_string(variable));
	sprintf(msg + i, "%f", heater->variables[variable]);
	send_msg(heater->sock_fd, heater->server, msg);
	recv_msg(heater->sock_fd, msg);
}

void control_temp(struct tq_elem *tqe)
{
	double C = 50000000;
	double k = 0.15 * C;

	struct boiler *heater = tq_data(tqe, struct boiler, tqe[0]);

	/* scheduler again the task */
	add_task(TS_TEMP, tqe, control_temp);

#ifdef DEBUG
	log_print(LOG_NOTICE, "controler_temp\n");
#endif

	/* Control temp */
	pthread_mutex_lock(&heater->mutex);

	heater->variables[T] = boiler_get_value(heater, T);
	log_print(LOG_NOTICE, "T = %f\n", heater->variables[T]);

	heater->variables[Q] = k * (heater->variables[TREF] - heater->variables[T]);
	if (heater->variables[Q] < 0)
		heater->variables[Q] = 0;
	else if (heater->variables[Q] > 1000000)
		heater->variables[Q] = 1000000;

	boiler_put_value(heater, Q);

	/* Warning temperature: send signal thread handler_alarms */ 
	if (heater->variables[T] > heater->variables[TREF]) {
		heater->flag |= 1;
		pthread_cond_signal(&heater->cond);
	}
	pthread_mutex_unlock(&heater->mutex);
}

void control_level(struct tq_elem *tqe)
{
	double k = 1200;
	struct boiler *heater = tq_data(tqe, struct boiler, tqe[1]);

	/* scheduler again the task */
	add_task(TS_LEVEL, tqe, control_level);

#ifdef DEBUG
	log_print(LOG_NOTICE, "controler_level\n");
#endif

	/* Control level */
	pthread_mutex_lock(&heater->mutex);

	heater->variables[H] = boiler_get_value(heater, H);
	log_print(LOG_NOTICE, "H = %f\n", heater->variables[H]);

	heater->variables[Ni] = k * (heater->variables[HREF] - heater->variables[H]);

	if (heater->variables[Ni] < 0)
		heater->variables[Ni] = 0;
	else if (heater->variables[Ni] > 100)
		heater->variables[Ni] = 100;
	
	boiler_put_value(heater, Ni);

	/* Warning level: send signal thread handler_alarms */
	if (heater->variables[H] <= 0.1 || heater->variables[H] > 3) {
		heater->flag |= 2; 
		pthread_cond_signal(&heater->cond);
	}

	pthread_mutex_unlock(&heater->mutex);
}

void refresh_screen(struct tq_elem *tqe)
{
	int i;
	struct boiler *heater = tq_data(tqe, struct boiler, tqe[2]);

	/* scheduler again the task */
	add_task(TS_SCREEN, tqe, refresh_screen);

#ifdef DEBUG
	log_print(LOG_NOTICE, "refresh_screen\n");
#endif

// "\033[2J"
	for (i = 0; i <= HREF; i++)
		printf("%s = %f \n", get_variable_string(i), heater->variables[i]);
}
